package com.dj.mingkong.common.infrastructure.base.repository;

import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.FluentQuery;

import java.io.Serializable;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

/**
 * @author zenglonghui
 * @date: 2022/5/17 17:29
 */
@NoRepositoryBean
public interface BaseMongodbRepository<T, ID extends Serializable> extends MongoRepository<T, ID> {
    /**
     * 根据id逻辑删除
     *
     * @param id ID
     */
    @Override
    void deleteById(@NotNull ID id);

    /**
     * 根据实体逻辑删除
     *
     * @param entity {}
     */
    @Override
    void delete(@NotNull T entity);

    /**
     * 逻辑删除所有
     */
    @Override
    void deleteAll();

    /**
     * 批量逻辑删除
     *
     * @param entities Iterable
     */
    @Override
    void deleteAll(@NotNull Iterable<? extends T> entities);

    /**
     * 根据id批量逻辑删除
     *
     * @param ids Iterable
     */
    @Override
    void deleteAllById(@NotNull Iterable<? extends ID> ids);

    /**
     * 获取所有
     *
     * @return T
     */
    @NotNull
    @Override
    @Query("{ 'deleted' : {$ne :1} }")
    List<T> findAll();

    /**
     * 根据排序获取所有
     *
     * @param sort {}
     * @return T
     */
    @Override
    @NotNull
    @Query("{ 'deleted' : {$ne :1} }")
    List<T> findAll(@NotNull Sort sort);

    /**
     * 根据条件获取所有
     *
     * @param example {}
     * @param <S>     S
     * @return S
     */
    @Override
    @NotNull
    <S extends T> List<S> findAll(@NotNull Example<S> example);

    /**
     * 根据条件排序获取所有
     *
     * @param example {}
     * @param sort    {}
     * @param <S>     S
     * @return S
     */
    @Override
    @NotNull
    <S extends T> List<S> findAll(@NotNull Example<S> example, @NotNull Sort sort);

    /**
     * 分页获取列表
     *
     * @param pageable {}
     * @return T
     */
    @Override
    @NotNull
    @Query("{ 'deleted' : {$ne :1} }")
    Page<T> findAll(@NotNull Pageable pageable);

    /**
     * 根据条件分页获取列表
     *
     * @param example  {}
     * @param pageable {}
     * @param <S>      S
     * @return S
     */
    @Override
    @NotNull
    <S extends T> Page<S> findAll(@NotNull Example<S> example, @NotNull Pageable pageable);

    /**
     * 根据ids获取列表
     *
     * @param ids Iterable
     * @return T
     */
    @Override
    @NotNull
    @Query("{ 'deleted' : {$ne :1} }")
    List<T> findAllById(@NotNull Iterable<ID> ids);

    /**
     * 根据id获取数据
     *
     * @param id ID
     * @return T
     */
    @Override
    @NotNull
    Optional<T> findById(@NotNull ID id);

    /**
     * 根据条件获取单个数据
     *
     * @param example {}
     * @param <S>     S
     * @return S
     */
    @Override
    @NotNull
    <S extends T> Optional<S> findOne(@NotNull Example<S> example);

    /**
     * 根据。。。查询
     *
     * @param example       {}
     * @param queryFunction {}
     * @param <S>           S
     * @param <R>           R
     * @return S
     */
    @Override
    @NotNull
    <S extends T, R> R findBy(@NotNull Example<S> example, @NotNull Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);

    /**
     * 查询数量
     *
     * @return long
     */
    @Override
    @Query("{ 'deleted' : {$ne :1} }")
    long count();

    /**
     * 根据条件获取数量
     *
     * @param example {}
     * @param <S>     S
     * @return S
     */
    @Override
    <S extends T> long count(@NotNull Example<S> example);

    /**
     * 根据id判断是否存在
     *
     * @param id ID
     * @return boolean
     */
    @Override
    @Query("{ 'deleted' : {$ne :1} }")
    boolean existsById(@NotNull ID id);

    /**
     * 根据条件判断是否存在
     *
     * @param example {}
     * @param <S> S
     * @return S
     */
    @Override
    <S extends T> boolean exists(@NotNull Example<S> example);
}
